import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * OutOfMemoryError就是经典的内存溢出的问题，而且他明确告诉你，是Metaspace这块区域内存溢出了。
 * -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
 */
public class MetaspaceDemo {
    public static void main(String[] args) {
        int count = 0;
        while(true){
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(Car.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    if (method.getName().equals("run")){
                        System.out.println("汽车启动前，要先检查检查身体！");
                        return methodProxy.invokeSuper(o,objects);
                    }
                    return methodProxy.invokeSuper(o,objects);
                }
            });
            System.out.println("第"+ count++ +"汽车启动");
            Car car = (Car) enhancer.create();
            car.run();
        }
    }

    static class Car{
        public void run(){
            System.out.println("老司机开车啦！！！");
        }
    }

    /**
     * -XX:+UseParNewGC
     * -XX:+UseConcMarkSweepGC
     * -XX:MetaspaceSize=10m
     * -XX:MaxMetaspaceSize=10m
     * -XX:+PrintGCDetails
     * -Xloggc:gc.log
     * -XX:+HeapDumpOnOutOfMemoryError
     * -XX:HeapDumpPath=./
     *
     * 接着我们用上述JVM参数运行这段程序，会发现项目下面多了两个文件，一个是gc.log，还有一个是java_pid910.hprof
     * 当然不同的机器运行这个hprof文件的名字是不太一样的，因为他会用你的PID进程id作为文件名字。
     * 接着我们先来分析一下gc.log，也就是分析一下他是如何拼命往Metaspace区域里放入大量生成的类，然后触发Full GC，
     * 接着回收Metaspace区域，回收后还是无法放下更多的类，接着才会抛出内存溢出的异常。
     * 然后我们再用MAT分析一下OOM的时候的内存快照，带着大家学习一下如何用MAT工具找到Metaspace内存溢出问题的原因。
     * 先把我这里的GC日志给大家抛出来，同时我们就跟着GC日志一行一行分析，到底是怎么回事，大家紧紧跟着脚步来走。
     */
}
